#include "gtest/gtest.h"
#include "DataStructure/Common/Constant.h"
#include "../../IntegrationFormula/Gauss2D2X2P.h"
#include "../Quad8NodeShpFunc.h"

using SG::DataStructure::Common::TOLERANCE;
using SG::Algebra::Matrixd;
using SG::FEMSolver::Element::Quad8NodeShpFunc;

// 形函数在本点为1，它点为0
TEST (Quad8NodeShpFuncTest, shpFuncTest)
{
    // Input
    SG::DataStructure::FEM::IntegPointArray integs (8);
    integs[0].m_x = -1.0; integs[0].m_y = -1.0;
    integs[1].m_x =  1.0; integs[1].m_y = -1.0;
    integs[2].m_x =  1.0; integs[2].m_y =  1.0;
    integs[3].m_x = -1.0; integs[3].m_y =  1.0;
    integs[4].m_x =  0.0; integs[4].m_y = -1.0;
    integs[5].m_x =  1.0; integs[5].m_y =  0.0;
    integs[6].m_x =  0.0; integs[6].m_y =  1.0;
    integs[7].m_x = -1.0; integs[7].m_y =  0.0;
    
    // Test data
    auto shpfunc = Quad8NodeShpFunc ();
    shpfunc.Compute (integs);

    // 测试 1号节点处形函数
    auto& m1Test = shpfunc.GetShapeFunction (0);
    auto m1Target = Matrixd (8, 1); m1Target (0, 0) = 1.0;
    ASSERT_TRUE (m1Test == m1Target);

    // 测试 2号节点处形函数
    auto& m2Test = shpfunc.GetShapeFunction (1);
    auto m2Target = Matrixd (8, 1); m2Target (1, 0) = 1.0;
    ASSERT_TRUE (m2Test == m2Target);

    // 测试 3号节点处形函数
    auto& m3Test = shpfunc.GetShapeFunction (2);
    auto m3Target = Matrixd (8, 1); m3Target (2, 0) = 1.0;
    ASSERT_TRUE (m3Test == m3Target);

    // 测试 4号节点处形函数
    auto& m4Test = shpfunc.GetShapeFunction (3);
    auto m4Target = Matrixd (8, 1); m4Target (3, 0) = 1.0;
    ASSERT_TRUE (m4Test == m4Target);

    // 测试 5号节点处形函数
    auto& m5Test = shpfunc.GetShapeFunction (4);
    auto m5Target = Matrixd (8, 1); m5Target (4, 0) = 1.0;
    ASSERT_TRUE (m5Test == m5Target);

    // 测试 6号节点处形函数
    auto& m6Test = shpfunc.GetShapeFunction (5);
    auto m6Target = Matrixd (8, 1); m6Target (5, 0) = 1.0;
    ASSERT_TRUE (m6Test == m6Target);

    // 测试 7号节点处形函数
    auto& m7Test = shpfunc.GetShapeFunction (6);
    auto m7Target = Matrixd (8, 1); m7Target (6, 0) = 1.0;
    ASSERT_TRUE (m7Test == m7Target);

    // 测试 8号节点处形函数
    auto& m8Test = shpfunc.GetShapeFunction (7);
    auto m8Target = Matrixd (8, 1); m8Target (7, 0) = 1.0;
    ASSERT_TRUE (m8Test == m8Target);
}

// 标准母元， jocobian为单位矩阵
TEST (Quad8NodeShpFuncTest, shpFuncDerivativeTest)
{
    // Input
    SG::FEMSolver::Element::Gauss2D2X2P integCalc;
    auto integs = integCalc.GetPoints ();
    Matrixd nodes (8, 2);
    nodes (0, 0) = -1.0; nodes (0, 1) = -1.0;
    nodes (1, 0) =  1.0; nodes (1, 1) = -1.0;
    nodes (2, 0) =  1.0; nodes (2, 1) =  1.0;
    nodes (3, 0) = -1.0; nodes (3, 1) =  1.0;
    nodes (4, 0) =  0.0; nodes (4, 1) = -1.0;
    nodes (5, 0) =  1.0; nodes (5, 1) =  0.0;
    nodes (6, 0) =  0.0; nodes (6, 1) =  1.0;
    nodes (7, 0) = -1.0; nodes (7, 1) =  0.0;
    
    // Target data
    auto I = SG::Algebra::identity (2);

    // Test data
    auto shpfunc = Quad8NodeShpFunc ();
    shpfunc.Compute (integs);

    // 测试4个积分点形函数导数
    for (std::size_t index = 0; index < 4; ++index)
    {
        auto I1 = shpfunc.GetShapeFunctionDerivative (index) * nodes;        
        ASSERT_TRUE (I1 == I);
    }
}